package mnn;

/*
 This program is written by Ahmed Medhat Ahmed
 Egypt
 Alexandria Universty
 Faculty of Science
 Computer Science
 7-7-2007
 a.medhat.cs@gmail.com
 ama_compsc@yahoo.com
 */
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.ScrollPane;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.ObjectOutputStream;

import javax.swing.BoxLayout;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;

public class TrainN extends JFrame { // implements ActionListener{
	/**
	 * 
	 */
	private static final long serialVersionUID = -5605114895041882101L;

	public static void main(String[] args) {
		TrainN app = new TrainN();
		app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}

	private JLabel L1, L2;
	private JLabel L_c, L_tc, L_in, L_hl, L_hn, L_lr, L_mr;

	private JTextField TF_c, TF_tc, TF_in, TF_hl, TF_hn, TF_lr, TF_mr;

	private JButton B_savenn, B_loadim, B_train;
	private BorderLayout layout;
	private GridLayout layoutL, layoutR;
	private Container container;

	private JPanel P_Top, P_Center, P_CenterL, P_CenterR, P_CenterC, P_Right,
			P_Left, P_Bottom;
	private JTextArea ta;

	private ScrollPane sp;

	private ObjectOutputStream output;
	/*
	 * Neural network variables
	 */
	private int in, out, hl, hn;

	private double lr, mr;
	private int no_tc;
	private int in_array[][][];

	private int out_array[][];
	private String img_names[];

	private File img_files[];
	private String traininfo;
	private int Dim[];

	private int Dim4[];

	private double weight[][][];

	private File fileName;
	private ImageP imagep;

	private Train train;

	public TrainN() {
		super("Neural Networkes System");

		container = getContentPane();
		container.setLayout(new BorderLayout(5, 5));

		P_Top = new JPanel();
		P_Top.setLayout(new FlowLayout());

		L1 = new JLabel();

		Icon img = new ImageIcon("1.jpg");
		L1.setIcon(img);

		P_Top.add(L1);

		/************************************************************************************/
		layout = new BorderLayout();
		P_Center = new JPanel();
		P_Center.setLayout(layout);

		P_CenterC = new JPanel();
		P_CenterC.setLayout(layout);

		layoutR = new GridLayout(7, 1, 10, 10);
		P_CenterR = new JPanel();
		P_CenterR.setLayout(layoutR);

		layoutL = new GridLayout(7, 1, 10, 10);
		P_CenterL = new JPanel();
		P_CenterL.setLayout(layoutL);

		// layoutR.setAlignment(FlowLayout.LEFT);
		// layoutL.setAlignment(FlowLayout.LEFT);

		L_c = new JLabel("Enter the number of classes                      ");
		L_tc = new JLabel("Enter the number of training cases in each class ");
		L_in = new JLabel("Enter the input value                            ");
		L_hl = new JLabel("Enter the number of hidden layer                 ");
		L_hn = new JLabel("Enter the number of hidden neurons               ");
		L_lr = new JLabel("Enter the value of learnning rate                ");
		L_mr = new JLabel("Enter the value of momentum rate                 ");

		TF_c = new JTextField(10);
		TF_tc = new JTextField(10);
		TF_in = new JTextField(10);
		TF_hl = new JTextField(10);
		TF_hn = new JTextField(10);
		TF_lr = new JTextField(10);
		TF_mr = new JTextField(10);

		P_CenterL.add(L_c);
		P_CenterR.add(TF_c);

		P_CenterL.add(L_tc);
		P_CenterR.add(TF_tc);

		P_CenterL.add(L_in);
		P_CenterR.add(TF_in);

		P_CenterL.add(L_hl);
		P_CenterR.add(TF_hl);

		P_CenterL.add(L_hn);
		P_CenterR.add(TF_hn);

		P_CenterL.add(L_lr);
		P_CenterR.add(TF_lr);

		P_CenterL.add(L_mr);
		P_CenterR.add(TF_mr);

		P_Right = new JPanel();
		P_Right.setLayout(new FlowLayout());

		L2 = new JLabel();
		P_Left = new JPanel();
		P_Left.setLayout(new FlowLayout());
		P_Left.add(L2);

		P_Center.add(P_CenterL, BorderLayout.WEST);
		P_Center.add(P_CenterR, BorderLayout.CENTER);
		P_Center.add(P_Right, BorderLayout.EAST);

		B_savenn = new JButton("Save NN");
		B_loadim = new JButton("Load Images");
		B_train = new JButton("Train");
		B_loadim.setEnabled(false);
		B_train.setEnabled(false);

		B_savenn.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				saveFile();

			}
		});
		B_loadim.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				openFile();

			}
		});
		B_train.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				/* Train the neural network */
				conv_img();
				get_output();
				train();
				printweight();
			}
		});
		JPanel p1 = new JPanel();
		p1.setLayout(new FlowLayout());
		JPanel p2 = new JPanel();
		p2.setLayout(new FlowLayout());
		P_Bottom = new JPanel();
		P_Bottom.setLayout(new BoxLayout(P_Bottom, BoxLayout.Y_AXIS));

		ta = new JTextArea();
		sp = new ScrollPane();
		sp.add(ta);
		// /ta.setSize(50,100);
		sp.setSize(350, 150);
		p1.add(sp);

		p2.add(B_savenn);
		p2.add(B_loadim);
		p2.add(B_train);

		/*
		 * P_Bottom.add(B_savenn); P_Bottom.add(B_loadim);
		 * P_Bottom.add(B_train);
		 */
		P_Bottom.add(p1);
		P_Bottom.add(p2);
		container.add(P_Top, BorderLayout.NORTH);
		container.add(P_Center, BorderLayout.CENTER);
		container.add(P_Bottom, BorderLayout.SOUTH);
		container.add(P_Right, BorderLayout.EAST);
		container.add(P_Left, BorderLayout.WEST);

		setLocation(150, 50);
		pack();
		setVisible(true);
		setResizable(false);
	}

	void conv_img() {
		imagep = new ImageP();
		in_array = new int[out][no_tc][in];
		for (int i = 0; i < out; i++) {
			for (int j = 0; j < no_tc; j++) {
				in_array[i][j] = imagep.conv_to_data(img_files[(i * no_tc + j)]
						.getAbsolutePath(), in);
			}
		}
	}

	void get_output() {
		out_array = new int[out][out];
		for (int i = 0; i < out; i++)
			for (int j = 0; j < out; j++)
				out_array[i][j] = (i == j ? 1 : 0);
	}

	private void openFile() {
		JFileChooser fileChooser = new JFileChooser();
		fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
		int result = fileChooser.showOpenDialog(this);
		if (result == JFileChooser.CANCEL_OPTION) {
			return;
		} else
			B_train.setEnabled(true);
		File DName = fileChooser.getSelectedFile();

		if (DName == null || DName.getName().equals(""))
			JOptionPane.showMessageDialog(this, "Invalid File Name",
					"Invalid file name", JOptionPane.ERROR_MESSAGE);
		else {
			if (DName.exists()) {
				String files[] = DName.list();
				File fl[] = new File[files.length];
				int counter = 0;
				for (int i = 0; i < files.length; i++) {
					fl[i] = new File(DName.getAbsolutePath() + "\\" + files[i]);
					if (!fl[i].isHidden() && fl[i].isFile()) {
						counter++;
					}
				}
				img_names = new String[counter];
				img_files = new File[counter];
				counter = 0;
				for (int i = 0; i < files.length; i++) {
					if (!fl[i].isHidden() && fl[i].isFile()) {
						img_names[counter++] = files[i];
					}
				}
				for (int i = 0; i < img_names.length; i++) {
					img_files[i] = new File(DName.getAbsolutePath() + "\\"
							+ img_names[i]);
					// JOptionPane.showMessageDialog(this,img_files[i]);
				}
			} else {
				JOptionPane.showMessageDialog(this, DName + " dosent exist");
			}
		}
	}

	void printweight() {
		FileWriter fw;
		BufferedWriter bw;
		String filexls;

		filexls = fileName.getAbsolutePath() + ".xls";
		File F = new File(filexls);
		if (F.exists())
			F.delete();
		try {
			fw = new FileWriter(filexls);
			bw = new BufferedWriter(fw);

			for (int i = 0; i < Dim[0]; i++) {
				for (int j = 0; j < Dim4[i]; j++) { // no of in nodes
					for (int k = 0; k < Dim4[i + 1]; k++) {// out nodes
						fw.append(weight[i][j][k] + " \n");
					}
				}
			}
			fw.close();
			bw.close();
			fw = null;
			bw = null;
		} catch (IOException ex) {
			JOptionPane.showMessageDialog(null, "Cant Save the weights");
		}
	}

	private void saveFile() {
		JFileChooser fileChooser = new JFileChooser();
		fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
		int result = fileChooser.showSaveDialog(this);

		if (result == JFileChooser.CANCEL_OPTION)
			return;
		else
			B_loadim.setEnabled(true);

		fileName = fileChooser.getSelectedFile();

		if (fileName == null || fileName.getName().equals(""))
			JOptionPane.showMessageDialog(this, "Invalid File Name",
					"Invalid file name", JOptionPane.ERROR_MESSAGE);
		else {
			try {
				output = new ObjectOutputStream(new FileOutputStream(fileName));
			} catch (IOException ioException) {
				JOptionPane.showMessageDialog(this, "Invalid File Name",
						"Error in opening file", JOptionPane.ERROR_MESSAGE);
			}
			try {
				StructuerNN struct;

				if (TF_c.getText().equals(""))
					out = 1;
				else
					out = Integer.parseInt(TF_c.getText());

				if (TF_tc.getText().equals(""))
					no_tc = 1;
				else
					no_tc = Integer.parseInt(TF_tc.getText());

				if (TF_in.getText().equals(""))
					in = 1;
				else
					in = Integer.parseInt(TF_in.getText());

				if (TF_hl.getText().equals(""))
					hl = 1;
				else
					hl = Integer.parseInt(TF_hl.getText());

				if (TF_hn.getText().equals(""))
					hn = 1;
				else
					hn = Integer.parseInt(TF_hn.getText());

				if (TF_lr.getText().equals(""))
					lr = .1;
				else
					lr = Double.parseDouble(TF_lr.getText());

				if (TF_mr.getText().equals(""))
					mr = .1;
				else
					mr = Double.parseDouble(TF_mr.getText());

				struct = new StructuerNN(in, out, hl, hn, lr, mr);
				output.writeObject(struct);
				// JOptionPane.showMessageDialog(null,struct.getinput());
				output.flush();
				output.close();
			} catch (NumberFormatException formatException) {
				JOptionPane.showMessageDialog(this, "bad ",
						"Invalied  Number Format", JOptionPane.ERROR_MESSAGE);
			} catch (IOException ioException) {
				JOptionPane.showMessageDialog(this, "Invalid File Name",
						"Error in opening file", JOptionPane.ERROR_MESSAGE);
			}
		}
	}

	void train() {
		Dim = new int[3];

		train = new Train(in, out, hl, hn, lr, mr, no_tc);
		train.start(in_array, out_array);

		traininfo = train.train_info();
		train.getweightsDim(Dim);

		weight = new double[Dim[0]][Dim[2]][Dim[2]];
		Dim4 = new int[Dim[1]];

		train.getweights(weight, Dim4);

		ta.setText(traininfo);
	}

}